﻿package net.wangit.jdbc.database;

import net.wangit.jdbc.JDBCException;

public class DB2 extends Database
{

	public DB2()
	{
		registerType(1, 1, "CHAR($p)");
		registerType(2, 12, "VARCHAR($p)");
		registerType(11, 5, "SMALLINT");
		registerType(12, 4, "INTEGER");
		registerType(13, -5, "BIGINT");
		registerType(21, 6, "FLOAT");
		registerType(22, 8, "DOUBLE");
		registerType(23, 3, "DECIMAL($p, $s)");
		registerType(31, 91, "DATE");
		registerType(32, 92, "TIME");
		registerType(33, 93, "TIMESTAMP");
		registerType(41, 2005, "CLOB($p)");
		registerType(43, 2004, "BLOB($p)");
	}

	public int getTypeCode(int sqlTypeCode, String columnTypeName, int precision, int scale)
		throws JDBCException
	{
		switch (sqlTypeCode)
		{
		case 1: // '\001'
			return 1;

		case 12: // '\f'
			return 2;

		case 5: // '\005'
			return 11;

		case 4: // '\004'
			return 12;

		case -5: 
			return 13;

		case 6: // '\006'
			return 21;

		case 8: // '\b'
			return 22;

		case 3: // '\003'
			return 23;

		case 91: // '['
			return 31;

		case 92: // '\\'
			return 32;

		case 93: // ']'
			return 33;

		case 2005: 
			return 41;

		case 2004: 
			return 43;
		}
		throw new JDBCException((new StringBuilder("Unsupported sqlType: sqlTypeCode=")).append(sqlTypeCode).append(",columnTypeName=").append(columnTypeName).toString());
	}

	public int getDefaultBatchSize()
	{
		return 0;
	}

	public String getAddColumnString()
	{
		return "add column";
	}

	public boolean supportsIdentityColumns()
	{
		return true;
	}

	public String getIdentitySelectString()
	{
		return "values IDENTITY_VAL_LOCAL()";
	}

	public String getIdentityColumnString()
	{
		return "not null generated by default as identity";
	}

	public String getIdentityInsertString()
	{
		return "default";
	}

	public String getSequenceNextValString(String sequenceName)
	{
		return (new StringBuilder("values nextval for ")).append(sequenceName).toString();
	}

	public String getCreateSequenceString(String sequenceName)
	{
		return (new StringBuilder("create sequence ")).append(sequenceName).toString();
	}

	public String getDropSequenceString(String sequenceName)
	{
		return (new StringBuilder("drop sequence ")).append(sequenceName).append(" restrict").toString();
	}

	public boolean supportsSequences()
	{
		return true;
	}

	public boolean supportsLimit()
	{
		return true;
	}

	public String getLimitString(String sql, boolean hasOffset)
	{
		StringBuffer rownumber = (new StringBuffer(50)).append(" rownumber() over(");
		int orderByIndex = sql.toLowerCase().indexOf("order by");
		if (orderByIndex > 0)
			rownumber.append(sql.substring(orderByIndex));
		rownumber.append(") as row_,");
		StringBuffer pagingSelect = (new StringBuffer(sql.length() + 100)).append("select * from ( ").append(sql).insert(getAfterSelectInsertPoint(sql), rownumber.toString()).append(" ) as temp_ where row_ ");
		if (hasOffset)
			pagingSelect.append("between ?+1 and ?");
		else
			pagingSelect.append("<= ?");
		return pagingSelect.toString();
	}

	public boolean useMaxForLimit()
	{
		return true;
	}

	private static int getAfterSelectInsertPoint(String sql)
	{
		return 16 + (sql.startsWith("select distinct") ? 15 : 6);
	}

	public String getQueryTableString(String tableName)
	{
		return (new StringBuilder("select tabname from syscat.tables where tabname = '")).append(tableName).append("'").toString();
	}
}
